package com.changgou.order.service.impl;

import com.changgou.entity.Constants;
import com.changgou.goods.feign.SkuFeign;
import com.changgou.order.config.RabbitMQConfig;
import com.changgou.order.dao.OrderItemMapper;
import com.changgou.order.dao.OrderLogMapper;
import com.changgou.order.dao.OrderMapper;
import com.changgou.order.pojo.OrderItem;
import com.changgou.order.pojo.OrderLog;
import com.changgou.order.service.CartService;
import com.changgou.order.service.OrderService;
import com.changgou.order.pojo.Order;
import com.changgou.pay.feign.PayFeign;
import com.changgou.util.IdWorker;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    //这里用spring注入
    @Autowired
    private CartService cartService;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private OrderLogMapper orderLogMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private PayFeign payFeign;

    /**
     * 查询全部列表
     * @return
     */
    @Override
    public List<Order> findAll() {
        return orderMapper.selectAll();
    }

    /**
     * 根据ID查询
     * @param id
     * @return
     */
    @Override
    public Order findById(String id){
        return  orderMapper.selectByPrimaryKey(id);
    }


    /**
     * 增加
     * @param order
     */
    @Override
    public void add(Order order){
        /**
         * 1.根据用户名获取购物车
         */
        Map<String, Object> cartMap = cartService.list(order.getUsername());

        /**
         * 2.保存订单, 到数据库的订单表
         */
        //总购买商品数量
        Integer totalNum = Integer.parseInt(String.valueOf(cartMap.get("totalNum")));
        //总价格
        Integer totalPrice = Integer.parseInt(String.valueOf(cartMap.get("totalPrice")));
        //获取购物车中的购物项集合
        Collection<OrderItem> orderItemList = (Collection<OrderItem>)cartMap.get("orderItemList");

        order.setId(String.valueOf(idWorker.nextId()));
        //总共购买商品数量
        order.setTotalNum(totalNum);
        //总金额
        order.setTotalMoney(totalPrice);
        //优惠金额
        order.setPreMoney(0);
        //邮费
        order.setPostFee(0);
        //支付金额
        order.setPayMoney(totalPrice);
        //创建时间
        order.setCreateTime(new Date());
        //更新时间
        order.setUpdateTime(new Date());
        //订单来源: 1:web，2：app，3：微信公众号，4：微信小程序  5 H5手机页面
        order.setSourceType("1");
        //订单状态: 未支付
        order.setOrderStatus(Constants.ORDER_STATUS_0);
        //支付状态: 0未支付
        order.setPayStatus("0");
        //发货状态: 0未发货
        order.setConsignStatus("0");
        orderMapper.insertSelective(order);

        /**
         * 3.订单保存到redis作为待支付订单, order_pay_用户名作为key, 订单对象作为value
         */
        redisTemplate.boundValueOps(Constants.REDIS_ORDER_PAY + order.getUsername()).set(order);

        /**
         * 4.保存订单详情到数据库订单详情表中
         */

        if (orderItemList != null) {
            for (OrderItem orderItem : orderItemList) {
                //订单id和订单详情关联
                orderItem.setOrderId(order.getId());
                orderItemMapper.insertSelective(orderItem);

                /**
                 * 5.减库存, 增加销量, 操作goods商品库的sku表
                 */
                skuFeign.decrCount(orderItem.getSkuId(), orderItem.getNum());
            }
        }

        /**
         * 6.清除redis中的购物车
         */
        redisTemplate.delete(Constants.REDIS_CART + order.getUsername());

        /**
         * 7. 将订单号发送到rabbitMq的relay_queue队列, 设置超时时间为20分钟.
         * 第一个参数: 发送到的延时消息队列名称
         * 第二个参数: 发送的内容, 这里是订单id
         * 第三个参数: MessagePostProcessor对象, 里面可以设置消息的超时时间
         */
        rabbitTemplate.convertAndSend(RabbitMQConfig.RELAY_QUEUE, (Object) order.getId(), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置超时时间为20分钟, 这里时间是毫秒为单位, 所以是1200000毫秒
                //如果开发测试阶段, 为了可以快速的测试到这块业务的代码, 所以需要将超时时间缩短, 这里设置为10秒
                message.getMessageProperties().setExpiration("10000");
                return message;
            }
        });
    }


    /**
     * 修改
     * @param order
     */
    @Override
    public void update(Order order){
        orderMapper.updateByPrimaryKey(order);
    }

    /**
     * 删除
     * @param id
     */
    @Override
    public void delete(String id){
        orderMapper.deleteByPrimaryKey(id);
    }


    /**
     * 条件查询
     * @param searchMap
     * @return
     */
    @Override
    public List<Order> findList(Map<String, Object> searchMap){
        Example example = createExample(searchMap);
        return orderMapper.selectByExample(example);
    }

    /**
     * 分页查询
     * @param page
     * @param size
     * @return
     */
    @Override
    public Page<Order> findPage(int page, int size){
        PageHelper.startPage(page,size);
        return (Page<Order>)orderMapper.selectAll();
    }

    /**
     * 条件+分页查询
     * @param searchMap 查询条件
     * @param page 页码
     * @param size 页大小
     * @return 分页结果
     */
    @Override
    public Page<Order> findPage(Map<String,Object> searchMap, int page, int size){
        PageHelper.startPage(page,size);
        Example example = createExample(searchMap);
        return (Page<Order>)orderMapper.selectByExample(example);
    }

    @Override
    public void paySuccess(String orderId, String transId) {
        //1. 根据订单id, 到数据库中获取订单数据
        Order order = orderMapper.selectByPrimaryKey(orderId);

        //如果订单状态是未支付状态, 进行支付成功业务处理
        if (Constants.ORDER_STATUS_0.equals(order.getOrderStatus())) {

            //2. 删除redis中的待支付订单对象
            redisTemplate.delete(Constants.REDIS_ORDER_PAY + order.getUsername());

            //3. 修改订单状态为已支付
            //修改时间
            order.setUpdateTime(new Date());
            //支付状态1, 已经支付
            order.setPayStatus("1");
            //支付时间
            order.setPayTime(new Date());
            //订单状态: 1, 已支付
            order.setOrderStatus(Constants.ORDER_STATUS_1);
            //交易流水号
            order.setTransactionId(transId);

            orderMapper.updateByPrimaryKeySelective(order);

            //4. 记录订单变动日志
            OrderLog orderLog = new OrderLog();
            //主键id
            orderLog.setId(String.valueOf(idWorker.nextId()));
            //发货状态: 0未发货
            orderLog.setConsignStatus("0");
            //支付状态: 1已支付
            orderLog.setPayStatus("1");
            //操作人, system代表系统自动操作
            orderLog.setOperater("system");
            //操作时间
            orderLog.setOperateTime(new Date());
            //订单id
            orderLog.setOrderId(order.getId());
            //订单状态, 1已支付
            orderLog.setOrderStatus(Constants.ORDER_STATUS_1);
            orderLogMapper.insertSelective(orderLog);
        }
    }

    @Override
    public void payTimeOut(Order order) {

        //1 调用微信关闭支付通道接口, 关闭支付通道
        payFeign.closePay(order.getId());

        //2 将数据库中订单的支付状态改为订单关闭
        //更新时间
        order.setUpdateTime(new Date());
        //订单关闭时间
        order.setCloseTime(new Date());
        //订单状态: 7订单关闭
        order.setOrderStatus(Constants.ORDER_STATUS_7);
        orderMapper.updateByPrimaryKeySelective(order);

        //3 恢复库存, 恢复销量
        OrderItem orderItemParam = new OrderItem();
        orderItemParam.setOrderId(order.getId());
        List<OrderItem> orderItemList = orderItemMapper.select(orderItemParam);
        if (orderItemList != null) {
            for (OrderItem orderItem : orderItemList) {
                skuFeign.incrCount(orderItem.getSkuId(), orderItem.getNum());
            }
        }


        //4 删除redis中的待支付订单对象
        redisTemplate.delete(Constants.REDIS_ORDER_PAY + order.getUsername());

        //5 记录订单变动日志
        OrderLog orderLog = new OrderLog();
        //主键id
        orderLog.setId(String.valueOf(idWorker.nextId()));
        //发货状态: 0未发货
        orderLog.setConsignStatus("0");
        //支付状态: 1已支付
        orderLog.setPayStatus("0");
        //操作人, system代表系统自动操作
        orderLog.setOperater("system");
        //操作时间
        orderLog.setOperateTime(new Date());
        //订单id
        orderLog.setOrderId(order.getId());
        //订单状态, 1已关闭
        orderLog.setOrderStatus(Constants.ORDER_STATUS_7);
        orderLogMapper.insertSelective(orderLog);
    }

    @Override
    public void batchSend(List<Order> orders) {
        if (orders != null) {
            //1. 遍历传入的订单集合对象
            for (Order order : orders) {
                //2. 判断物流公司名称不能为空
                if (StringUtils.isEmpty(order.getShippingName())){
                    throw new RuntimeException("物流公司名称不能为空");
                }
                //3. 判断物流单号不能为空
                if (StringUtils.isEmpty(order.getShippingCode())) {
                    throw new RuntimeException("物流单号不能为空");
                }

                //设置发货状态为1, 已发货
                order.setConsignStatus("1");
                order.setUpdateTime(new Date());
                //订单状态: 2已发货
                order.setOrderStatus(Constants.ORDER_STATUS_2);
                //发货时间
                order.setConsignTime(new Date());

                /**
                 * 4. 判断发货状态必须是未发货的, 支付状态必须是已支付的
                 * 5. 更改发货状态为已发货
                 */
                //封装修改条件对象
                Example example = new Example(Order.class);
                //创建sql语句中的where条件对象
                Example.Criteria criteria = example.createCriteria();
                //订单id
                criteria.andEqualTo("id", order.getId());
                //支付状态为1, 已支付
                criteria.andEqualTo("payStatus", "1");
                //发货状态为0, 未返货
                criteria.andEqualTo("consignStatus", "0");
                orderMapper.updateByExampleSelective(order, example);

                /**
                 * 6. 记录订单变动日志
                 */
                OrderLog orderLog = new OrderLog();
                //主键id
                orderLog.setId(String.valueOf(idWorker.nextId()));
                //发货状态: 1已发货
                orderLog.setConsignStatus("1");
                //支付状态: 1已支付
                orderLog.setPayStatus("1");
                //操作人, system代表系统自动操作
                orderLog.setOperater("system");
                //操作时间
                orderLog.setOperateTime(new Date());
                //订单id
                orderLog.setOrderId(order.getId());
                //订单状态, 2已发货
                orderLog.setOrderStatus(Constants.ORDER_STATUS_2);
                orderLogMapper.insertSelective(orderLog);

            }
        }
    }

    @Override
    public void take(String orderId, String operater) {
        /**
         * 1. 修改订单状态为已收货
         */
        Order order = new Order();
        order.setId(orderId);
        //发货状态: 2已收货
        order.setConsignStatus("2");
        order.setUpdateTime(new Date());
        //交易完成时间
        order.setEndTime(new Date());
        //订单状态:6已完成
        order.setOrderStatus(Constants.ORDER_STATUS_6);

        orderMapper.updateByPrimaryKeySelective(order);

        /**
         * 2. 记录订单变动日志
         */
        OrderLog orderLog = new OrderLog();
        //主键id
        orderLog.setId(String.valueOf(idWorker.nextId()));
        //发货状态: 2已收货
        orderLog.setConsignStatus("2");
        //支付状态: 1已支付
        orderLog.setPayStatus("1");
        //操作人
        orderLog.setOperater(operater);
        //操作时间
        orderLog.setOperateTime(new Date());
        //订单id
        orderLog.setOrderId(order.getId());
        //订单状态, 6已完成
        orderLog.setOrderStatus(Constants.ORDER_STATUS_6);
        orderLogMapper.insertSelective(orderLog);

    }

    /**
     * 构建查询对象
     * @param searchMap
     * @return
     */
    private Example createExample(Map<String, Object> searchMap){
        Example example=new Example(Order.class);
        Example.Criteria criteria = example.createCriteria();
        if(searchMap!=null){
            // 订单id
            if(searchMap.get("id")!=null && !"".equals(searchMap.get("id"))){
                criteria.andEqualTo("id",searchMap.get("id"));
           	}
            // 支付类型，1、在线支付、0 货到付款
            if(searchMap.get("payType")!=null && !"".equals(searchMap.get("payType"))){
                criteria.andEqualTo("payType",searchMap.get("payType"));
           	}
            // 物流名称
            if(searchMap.get("shippingName")!=null && !"".equals(searchMap.get("shippingName"))){
                criteria.andLike("shippingName","%"+searchMap.get("shippingName")+"%");
           	}
            // 物流单号
            if(searchMap.get("shippingCode")!=null && !"".equals(searchMap.get("shippingCode"))){
                criteria.andLike("shippingCode","%"+searchMap.get("shippingCode")+"%");
           	}
            // 用户名称
            if(searchMap.get("username")!=null && !"".equals(searchMap.get("username"))){
                criteria.andLike("username","%"+searchMap.get("username")+"%");
           	}
            // 买家留言
            if(searchMap.get("buyerMessage")!=null && !"".equals(searchMap.get("buyerMessage"))){
                criteria.andLike("buyerMessage","%"+searchMap.get("buyerMessage")+"%");
           	}
            // 是否评价
            if(searchMap.get("buyerRate")!=null && !"".equals(searchMap.get("buyerRate"))){
                criteria.andLike("buyerRate","%"+searchMap.get("buyerRate")+"%");
           	}
            // 收货人
            if(searchMap.get("receiverContact")!=null && !"".equals(searchMap.get("receiverContact"))){
                criteria.andLike("receiverContact","%"+searchMap.get("receiverContact")+"%");
           	}
            // 收货人手机
            if(searchMap.get("receiverMobile")!=null && !"".equals(searchMap.get("receiverMobile"))){
                criteria.andLike("receiverMobile","%"+searchMap.get("receiverMobile")+"%");
           	}
            // 收货人地址
            if(searchMap.get("receiverAddress")!=null && !"".equals(searchMap.get("receiverAddress"))){
                criteria.andLike("receiverAddress","%"+searchMap.get("receiverAddress")+"%");
           	}
            // 订单来源：1:web，2：app，3：微信公众号，4：微信小程序  5 H5手机页面
            if(searchMap.get("sourceType")!=null && !"".equals(searchMap.get("sourceType"))){
                criteria.andEqualTo("sourceType",searchMap.get("sourceType"));
           	}
            // 交易流水号
            if(searchMap.get("transactionId")!=null && !"".equals(searchMap.get("transactionId"))){
                criteria.andLike("transactionId","%"+searchMap.get("transactionId")+"%");
           	}
            // 订单状态
            if(searchMap.get("orderStatus")!=null && !"".equals(searchMap.get("orderStatus"))){
                criteria.andEqualTo("orderStatus",searchMap.get("orderStatus"));
           	}
            // 支付状态
            if(searchMap.get("payStatus")!=null && !"".equals(searchMap.get("payStatus"))){
                criteria.andEqualTo("payStatus",searchMap.get("payStatus"));
           	}
            // 发货状态
            if(searchMap.get("consignStatus")!=null && !"".equals(searchMap.get("consignStatus"))){
                criteria.andEqualTo("consignStatus",searchMap.get("consignStatus"));
           	}
            // 是否删除
            if(searchMap.get("isDelete")!=null && !"".equals(searchMap.get("isDelete"))){
                criteria.andEqualTo("isDelete",searchMap.get("isDelete"));
           	}

            // 数量合计
            if(searchMap.get("totalNum")!=null ){
                criteria.andEqualTo("totalNum",searchMap.get("totalNum"));
            }
            // 金额合计
            if(searchMap.get("totalMoney")!=null ){
                criteria.andEqualTo("totalMoney",searchMap.get("totalMoney"));
            }
            // 优惠金额
            if(searchMap.get("preMoney")!=null ){
                criteria.andEqualTo("preMoney",searchMap.get("preMoney"));
            }
            // 邮费
            if(searchMap.get("postFee")!=null ){
                criteria.andEqualTo("postFee",searchMap.get("postFee"));
            }
            // 实付金额
            if(searchMap.get("payMoney")!=null ){
                criteria.andEqualTo("payMoney",searchMap.get("payMoney"));
            }

        }
        return example;
    }

}
